package manager.modulo.ordemservico.dao;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.LinkedList;
import manager.auxiliares.Configurations;
import manager.auxiliares.Format;
import manager.auxiliares.MensagemExcessao;
import manager.interfaces.InterfaceDao;
import manager.modulo.ordemservico.enumerator.EnumSituacaoOrdemServico;
import manager.modulo.ordemservico.enumerator.EnumSituacaoOrdemServico.SituacaoOS;
import manager.modulo.ordemservico.enumerator.EnumTipoOrdemServico;
import manager.modulo.ordemservico.enumerator.EnumTipoOrdemServico.TipoOS;
import manager.principal.fonte.JanelaLogin;

/**
 * Esta classe será utilizada para cadastra a entidade user no banco de dados
 *
 * @author Thiago
 */
public class OrdemServicoDao implements InterfaceDao {

    private int id;
    private boolean emitida;
    private boolean finalizada;
    private boolean avaliada;
    private TipoOS tipo;
    private String problemaInformado;
    private String complemento;
    private String dificuldades;
    private String materialUtilizado;
    private boolean necessitaAvaliacao;
    private int idProcedimento;
    private int idPontoAtendimento;

    /**
     * Inicializando as variáveis
     */
    public OrdemServicoDao() {
        id = 0;
        emitida = false;
        finalizada = false;
        avaliada = false;
        tipo = TipoOS.DEMANDA;
        problemaInformado = "";
        complemento = "";
        dificuldades = "";
        materialUtilizado = "";
        necessitaAvaliacao = false;
        idProcedimento = 0;
        idPontoAtendimento = 0;
    }

    public LinkedList<String> buscar(String opcao, String buscado, boolean limite) throws SQLException {
        LinkedList<String> result = new LinkedList<String>();
        if (!buscado.equals("")) {
            String sql = "";
            String tamanhoBusca = limite ? ("LIMIT 0," + Configurations.getAutoCompleteSizeSearch()) : "";
            if (opcao.equalsIgnoreCase("Ponto de Atendimento")) {
                sql = "SELECT tx_identificador FROM ponto_atendimento WHERE tx_identificador LIKE ? ORDER BY tx_identificador " + tamanhoBusca;
                buscado += "%";
            } else if (opcao.equalsIgnoreCase("Número da OS")) {
                sql = "SELECT id FROM ordem_servico WHERE id LIKE ? ORDER BY id " + tamanhoBusca;
                buscado += "%";
            } else if (opcao.equalsIgnoreCase("Procedimento")) {
                sql = "SELECT tx_nome FROM procedimento WHERE tx_nome LIKE ? ORDER BY tx_nome " + tamanhoBusca;
                buscado += "%";
            }
            if (!sql.equals("")) {
                PreparedStatement preparedStatement = JanelaLogin.getConnection().prepareStatement(sql);
                preparedStatement.setString(1, buscado);
                ResultSet resultSet = preparedStatement.executeQuery();
                while (resultSet.next()) {
                    result.add(resultSet.getString(1));
                }
            }
        }
        return result;
    }

    public static LinkedList buscaTabela(String opcao, String buscado, HashMap<String, Object> filtros) throws SQLException {
        LinkedList result = new LinkedList();
        Timestamp filtroInicioData = (filtros.containsKey("dataInicio") ? (Timestamp) filtros.get("dataInicio") : null);
        Timestamp filtroFimData = (filtros.containsKey("dataFim") ? (Timestamp) filtros.get("dataFim") : null);
        String filtroSituacao = (filtros.containsKey("situacao") ? (String) filtros.get("situacao") : null);
        if (!buscado.equals("")) {
            String sql = "";
            if (opcao.equalsIgnoreCase("Ponto de Atendimento")) { // Buscando por email
                sql = "SELECT"
                        + "  os.id AS Id,"
                        + "  pa.tx_identificador AS PontoAtendimento,"
                        + "  pr.tx_nome AS Procedimento,"
                        + "  sos.cd_situacao AS Situacao,"
                        + "  sos.dt_modificacao AS Modificacao,"
                        + "  psos.dt_modificacao AS Cadastro,"
                        + "  u.tx_nome AS Usuario"
                        + " FROM "
                        + "  ordem_servico os"
                        + "  INNER JOIN ponto_atendimento pa ON pa.id = os.id_pont_atend"
                        + "  INNER JOIN unidade_atendimento ua ON ua.id = pa.id_unidade_atendimento"
                        + "  INNER JOIN situacao_ord_serv sos ON sos.id_ord_serv = os.id AND sos.fl_ativo = true"
                        + "  INNER JOIN usuario u ON u.id = sos.id_usuario "
                        + "  INNER JOIN situacao_ord_serv psos ON psos.id_ord_serv = os.id AND psos.cd_situacao = ? "
                        + "  INNER JOIN procedimento pr ON pr.id = os.id_procedimento"
                        + " WHERE "
                        + "  pa.tx_identificador LIKE ? AND"
                        + "  (? IS NULL OR sos.cd_situacao = ?) AND"
                        + "  ((? IS NOT NULL AND ? IS NOT NULL AND psos.dt_modificacao>= ? AND psos.dt_modificacao<= ?) "
                        + "     OR (? IS NULL AND ? IS NULL AND psos.dt_modificacao <= CURRENT_TIMESTAMP() ))"
                        + " ORDER BY "
                        + "  os.id DESC";
                buscado += "%";
            } else if (opcao.equalsIgnoreCase("Número da OS")) {
                sql = "SELECT"
                        + "  os.id AS Id,"
                        + "  pa.tx_identificador AS PontoAtendimento,"
                        + "  pr.tx_nome AS Procedimento,"
                        + "  sos.cd_situacao AS Situacao,"
                        + "  sos.dt_modificacao AS Modificacao,"
                        + "  psos.dt_modificacao AS Cadastro,"
                        + "  u.tx_nome AS Usuario"
                        + " FROM "
                        + "  ordem_servico os"
                        + "  INNER JOIN ponto_atendimento pa ON pa.id = os.id_pont_atend"
                        + "  INNER JOIN unidade_atendimento ua ON ua.id = pa.id_unidade_atendimento"
                        + "  INNER JOIN situacao_ord_serv sos ON sos.id_ord_serv = os.id AND sos.fl_ativo = true"
                        + "  INNER JOIN usuario u ON u.id = sos.id_usuario "
                        + "  INNER JOIN situacao_ord_serv psos ON psos.id_ord_serv = os.id AND psos.cd_situacao = ? "
                        + "  INNER JOIN procedimento pr ON pr.id = os.id_procedimento"
                        + " WHERE "
                        + "  os.id LIKE ? AND"
                        + "  (? IS NULL OR sos.cd_situacao = ?) AND"
                        + "  ((? IS NOT NULL AND ? IS NOT NULL AND psos.dt_modificacao>= ? AND psos.dt_modificacao<= ?) "
                        + "     OR (? IS NULL AND ? IS NULL AND psos.dt_modificacao <= CURRENT_TIMESTAMP() ))"
                        + " ORDER BY "
                        + "  os.id DESC";
                buscado += "%";
            } else if (opcao.equalsIgnoreCase("Procedimento")) {
                sql = "SELECT"
                        + "  os.id AS Id,"
                        + "  pa.tx_identificador AS PontoAtendimento,"
                        + "  pr.tx_nome AS Procedimento,"
                        + "  sos.cd_situacao AS Situacao,"
                        + "  sos.dt_modificacao AS Modificacao,"
                        + "  psos.dt_modificacao AS Cadastro,"
                        + "  u.tx_nome AS Usuario"
                        + " FROM "
                        + "  ordem_servico os"
                        + "  INNER JOIN ponto_atendimento pa ON pa.id = os.id_pont_atend"
                        + "  INNER JOIN unidade_atendimento ua ON ua.id = pa.id_unidade_atendimento"
                        + "  INNER JOIN situacao_ord_serv sos ON sos.id_ord_serv = os.id AND sos.fl_ativo = true"
                        + "  INNER JOIN usuario u ON u.id = sos.id_usuario "
                        + "  INNER JOIN situacao_ord_serv psos ON psos.id_ord_serv = os.id AND psos.cd_situacao = ? "
                        + "  INNER JOIN procedimento pr ON pr.id = os.id_procedimento"
                        + " WHERE "
                        + "  pr.tx_nome LIKE ? AND"
                        + "  (? IS NULL OR sos.cd_situacao = ?) AND"
                        + "  ((? IS NOT NULL AND ? IS NOT NULL AND psos.dt_modificacao>= ? AND psos.dt_modificacao<= ?) "
                        + "     OR (? IS NULL AND ? IS NULL AND psos.dt_modificacao <= CURRENT_TIMESTAMP() ))"
                        + " ORDER BY "
                        + "  os.id DESC";
                buscado += "%";
            }
            if (!sql.equals("")) {
                PreparedStatement preparedStatement = JanelaLogin.getConnection().prepareStatement(sql);
                preparedStatement.setInt(1, EnumSituacaoOrdemServico.ConverterEnumNumero(SituacaoOS.EMABERTO));
                preparedStatement.setString(2, buscado);
                preparedStatement.setString(3, filtroSituacao);
                preparedStatement.setString(4, filtroSituacao);
                preparedStatement.setTimestamp(5, filtroInicioData);
                preparedStatement.setTimestamp(6, filtroFimData);
                preparedStatement.setTimestamp(7, filtroInicioData);
                preparedStatement.setTimestamp(8, filtroFimData);
                preparedStatement.setTimestamp(9, filtroInicioData);
                preparedStatement.setTimestamp(10, filtroFimData);
                ResultSet resultSet = preparedStatement.executeQuery();

                LinkedList<String> numeroOs = new LinkedList<String>();
                LinkedList<String> procedimento = new LinkedList<String>();
                LinkedList<String> pontoAtendimento = new LinkedList<String>();
                LinkedList<String> dataCadastro = new LinkedList<String>();
                LinkedList<String> ultimaModificacao = new LinkedList<String>();
                LinkedList<String> usuario = new LinkedList<String>();
                LinkedList<String> situacao = new LinkedList<String>();
                LinkedList<Integer> columnId = new LinkedList<Integer>();

                while (resultSet.next()) {
                    columnId.add(resultSet.getInt("Id"));
                    numeroOs.add(resultSet.getString("Id"));
                    procedimento.add(resultSet.getString("Procedimento"));
                    pontoAtendimento.add(resultSet.getString("PontoAtendimento"));
                    dataCadastro.add(Format.formatTimeStampToCompleteDatetime(resultSet.getTimestamp("Cadastro")));
                    ultimaModificacao.add(Format.formatTimeStampToCompleteDatetime(resultSet.getTimestamp("Modificacao")));
                    situacao.add(EnumSituacaoOrdemServico.ConvertEnumString(EnumSituacaoOrdemServico.ConverterNumeroEnum(resultSet.getInt("Situacao"))));
                    usuario.add(resultSet.getString("Usuario"));
                }

                result.add(columnId);
                result.add(Format.getBooleanLinkedList(columnId.size()));
                result.add(numeroOs);
                result.add(procedimento);
                result.add(pontoAtendimento);
                result.add(dataCadastro);
                result.add(ultimaModificacao);
                result.add(usuario);
                result.add(situacao);
                result.add(Format.getBooleanLinkedList(columnId.size()));
            }
        }
        return result;
    }

    /**
     * Carregar as informações do objeto ordem_servico a partir de um id
     *
     * @param id Id da os buscada
     */
    public void buscar(int id) {
        try {
            setId(id);
            String sql = "SELECT * FROM ordem_servico WHERE id = ?";
            PreparedStatement preparedStatement = JanelaLogin.getConnection().prepareStatement(sql);
            preparedStatement.setInt(1, id);
            ResultSet resultSet = preparedStatement.executeQuery();
            if (resultSet.first()) {
                emitida = resultSet.getBoolean("fl_emitida");
                finalizada = resultSet.getBoolean("fl_finalizada");
                avaliada = resultSet.getBoolean("fl_avaliada");
                tipo = EnumTipoOrdemServico.ConverterNumeroEnum(resultSet.getInt("cd_tipo"));
                problemaInformado = resultSet.getString("tx_problema");
                complemento = resultSet.getString("tx_complemento");
                dificuldades = resultSet.getString("tx_dificuldades");
                necessitaAvaliacao = resultSet.getBoolean("fl_nec_avaliacao");
                materialUtilizado = resultSet.getString("tx_material_utilizado");
                idProcedimento = resultSet.getInt("id_procedimento");
                idPontoAtendimento = resultSet.getInt("id_pont_atend");
            }
            resultSet.close();
            preparedStatement.close();
        } catch (Exception e) {
            MensagemExcessao.mostrarMensagem(e, "Buscando Ordens de Serviço");
        }
    }

    /**
     * Insere um usuário no banco
     */
    public void inserir() throws SQLException {
        String sql = "INSERT INTO ordem_servico (fl_emitida,fl_finalizada,cd_tipo,tx_problema,tx_complemento,tx_dificuldades,fl_nec_avaliacao,tx_material_utilizado,id_procedimento,id_pont_atend,fl_avaliada) VALUES(?,?,?,?,?,?,?,?,?,?,?)";
        PreparedStatement preparedStatement = JanelaLogin.getConnection().prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);

        preparedStatement.setBoolean(1, emitida);
        preparedStatement.setBoolean(2, finalizada);
        preparedStatement.setInt(3, EnumTipoOrdemServico.ConverterEnumNumero(tipo));
        preparedStatement.setString(4, problemaInformado);
        preparedStatement.setString(5, complemento);
        preparedStatement.setString(6, dificuldades);
        preparedStatement.setBoolean(7, necessitaAvaliacao);
        preparedStatement.setString(8, materialUtilizado);
        preparedStatement.setInt(9, idProcedimento);
        preparedStatement.setInt(10, idPontoAtendimento);
        preparedStatement.setBoolean(11, avaliada);
        preparedStatement.executeUpdate();

        //Recebendo o novo id gerado
        ResultSet resultSet = preparedStatement.getGeneratedKeys();
        while (resultSet.next()) {
            id = resultSet.getInt(1);
        }

        preparedStatement.close();
        resultSet.close();
    }

    /**
     * Atualiza o usuário no banco
     */
    public void atualizar() throws SQLException {
        String sql = "UPDATE ordem_servico SET  fl_emitida = ? , fl_finalizada = ? , cd_tipo = ? , tx_problema = ? , "
                + " tx_complemento = ? , tx_dificuldades = ? , fl_nec_avaliacao = ? , tx_material_utilizado = ? , "
                + " id_procedimento = ? , id_pont_atend = ? , fl_avaliada = ? WHERE id = ?";
        PreparedStatement preparedStatement = JanelaLogin.getConnection().prepareStatement(sql);
        preparedStatement.setBoolean(1, emitida);
        preparedStatement.setBoolean(2, finalizada);
        preparedStatement.setInt(3, EnumTipoOrdemServico.ConverterEnumNumero(tipo));
        preparedStatement.setString(4, problemaInformado);
        preparedStatement.setString(5, complemento);
        preparedStatement.setString(6, dificuldades);
        preparedStatement.setBoolean(7, necessitaAvaliacao);
        preparedStatement.setString(8, materialUtilizado);
        preparedStatement.setInt(9, idProcedimento);
        preparedStatement.setInt(10, idPontoAtendimento);
        preparedStatement.setBoolean(11, avaliada);
        preparedStatement.setInt(12, id);
        preparedStatement.executeUpdate();
        preparedStatement.close();
    }

    public void deletar() throws SQLException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public String getComplemento() {
        return complemento;
    }

    public void setComplemento(String complemento) {
        this.complemento = complemento;
    }

    public String getDificuldades() {
        return dificuldades;
    }

    public void setDificuldades(String dificuldades) {
        this.dificuldades = dificuldades;
    }

    public boolean isEmitida() {
        return emitida;
    }

    public void setEmitida(boolean emitida) {
        this.emitida = emitida;
    }

    public boolean isFinalizada() {
        return finalizada;
    }

    public void setFinalizada(boolean finalizada) {
        this.finalizada = finalizada;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getIdPontoAtendimento() {
        return idPontoAtendimento;
    }

    public void setIdPontoAtendimento(int idPontoAtendimento) {
        this.idPontoAtendimento = idPontoAtendimento;
    }

    public int getIdProcedimento() {
        return idProcedimento;
    }

    public void setIdProcedimento(int idProcedimento) {
        this.idProcedimento = idProcedimento;
    }

    public String getMaterialUtilizado() {
        return materialUtilizado;
    }

    public void setMaterialUtilizado(String materialUtilizado) {
        this.materialUtilizado = materialUtilizado;
    }

    public boolean isNecessitaAvaliacao() {
        return necessitaAvaliacao;
    }

    public void setNecessitaAvaliacao(boolean necessitaAvaliacao) {
        this.necessitaAvaliacao = necessitaAvaliacao;
    }

    public String getProblemaInformado() {
        return problemaInformado;
    }

    public void setProblemaInformado(String problemaInformado) {
        this.problemaInformado = problemaInformado;
    }

    public TipoOS getTipo() {
        return tipo;
    }

    public void setTipo(TipoOS tipo) {
        this.tipo = tipo;
    }

    public boolean isAvaliada() {
        return avaliada;
    }

    public void setAvaliada(boolean avaliada) {
        this.avaliada = avaliada;
    }
}
